/**
 * author：小小游 - allen
 * date：2019.11.08
 * lastUpdateDate：2020.05.23
 * description: http.js作用是axios封装 --- 请求拦截、响应拦截、错误统一处理
 */
import axios from 'axios';
import router from '../router';
import store from '../store';
import { Message } from 'element-ui';

/**
 * 提示函数
 * 禁止点击蒙层、显示一秒后关闭
 */
const tip = msg => {
    Message({
        type: 'error',
        message: msg,
        duration: 1000
    });
};

/**
 * 跳转登录页
 * 携带当前页面路由，在登录页面完成以前登录后返回当前页面
 */
const toLogin = () => {
    router.replace({
        path: '/user/login',
        // 携带当前路由的全路径，才知道从哪里跳回的登录页
        query: {
            redirect: router.currentRoute.fullPath
        }
    });
};

/**
 * 请求失败后的错误统一处理
 * @param {Number} status 请求失败的状态码
 */
const errorHandle = (status, other) => {
    // 状态码判断
    switch (status) {
        // 401: 未登录状态，比如token过期失效
        // 未登录则跳转登录页面，并携带当前页面的路径    
        // 在登录成功后返回当前页面，这一步需要在登录页操作
        case 401:
            tip('token过期，请重新登录！');
            window.localStorage.removeItem(
                'token'
            );
            setTimeout(() => {
                toLogin();
            }, 3000);
            break;
        // 404请求不存在
        case 404:
            tip('请求的资源不存在！');
            break;
        // 其它错误，直接抛出错误提示
        default:
            console.log(other);
            break;
    }
};

// 创建axios实例
let instance = axios.create({
    // 允许携带cookie
    withCredentials: true,
    // 过期时间
    timeout: 50 * 1000
});

// 设置post请求头
instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

// 设置post请求头
// instance.defaults.headers.post['Content-Type'] = 'application/json; charset=UTF-8';

/**
 * 请求拦截器
 * 每次请求前，如果存在token则在请求头中携带token
 */
instance.interceptors.request.use(
    config => {
        // 登录流程控制中，根据本地是否存在token判断用户的登录情况
        // 但是即使token存在，也有可能token是过期的，所以在每次的请求头中携带token
        // 后台根据携带的token判断用户的登录情况，并返回给我们对应的状态码
        // 而后我们可以在响应拦截器中，根据状态码进行一些统一的操作
        const token = store.state.getTokenModule.token;
        // token && (config.headers.Authorization = 'Bearer ' + token);
        token && (config.headers.Authorization = token);
        return config;
    },
    error => Promise.error(error)
);

// 响应拦截器
instance.interceptors.response.use(
    // 请求成功
    res => (res.status >= 200 && res.status < 300) || res.status == 304 ? Promise.resolve(res) : Promise.reject(res),
    // 请求失败
    error => {
        const {
            response
        } = error;
        if (response) {
            // 请求已发出，但是不在2xx的范围
            errorHandle(
                response.status,
                response.data.message
            );
            return Promise.reject(response);
        }
    }
);

export default instance;
